﻿using Furion.CMS.Application.Dto;
using Furion.CMS.Domain;
using Furion.DatabaseAccessor;
using Mapster;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Furion.CMS.Core.Base;
using Microsoft.AspNetCore.Mvc;
using Furion.FriendlyException;
using Microsoft.AspNetCore.Authorization;
using System.ComponentModel;
using System.Collections.Generic;

namespace Furion.CMS.Application
{
    /// <summary>
    /// 登录日志记录
    /// </summary>
    [DisplayName("LoginAuditLogs")]
    public class LoginRecordAppService : ReadOnlyAppService<UserLoginRecord, int, LoginRecordDto, LoginRecordDetailDto, LoginRecordFilter, LoginRecordSort>
    {
        private readonly IRepository<Blacklist> _blacklistRepository;

        /// <summary>
        /// 登录记录
        /// </summary>
        /// <param name="loginRecordRepository"></param>
        /// <param name="blacklistRepository"></param>
        public LoginRecordAppService(IRepository<UserLoginRecord> loginRecordRepository,
            IRepository<Blacklist> blacklistRepository)
            : base(loginRecordRepository)
        {
            _blacklistRepository = blacklistRepository;
        }

        protected override List<LoginRecordDto> PagedlistFilterEndQueryHandle(IQueryable<UserLoginRecord> entities)
        {
            return (from a in entities.ProjectToType<LoginRecordDto>()
                    join b in _blacklistRepository.AsQueryable(false) on a.Host equals b.HostAddress into temp
                    from c in temp.DefaultIfEmpty()
                    select a.SetBlacklist(c)).ToList();
        }

        protected override IQueryable<UserLoginRecord> DetailFilterEndQueryHandle(IQueryable<UserLoginRecord> entities)
        {
            entities = entities.Include(i => i.Passport)
             .ThenInclude(i => i.User);
            return entities;
        }

        protected override LoginRecordDetailDto AfterGetDetail(UserLoginRecord entity)
        {
            var hasBlacklist = _blacklistRepository.AsQueryable(false).Any(t => t.HostAddress == entity.Host);
            var dto = base.AfterGetDetail(entity);
            dto.HasBlacklist = hasBlacklist;

            return dto;
        }

        //protected override IQueryable<LoginRecordDetailDto> DetailFilterEndQueryHandle(IQueryable<UserLoginRecord> entities)
        //{
        //    entities = entities.Include(i => i.Passport)
        //        .ThenInclude(i => i.User);
        //    return (from a in entities.ProjectToType<LoginRecordDetailDto>()
        //            join b in _blacklistRepository.AsQueryable(false) on a.Host equals b.HostAddress into temp
        //            from c in temp.DefaultIfEmpty()
        //            select a.SetBlacklist(c))
        //                  .Cast<LoginRecordDetailDto>();
        //}

        /// <summary>
        /// 获取关联记录
        /// </summary>
        /// <param name="id">目标记录id</param>
        /// <param name="index">当前页码</param>
        /// <param name="limit">每页数量</param>
        /// <param name="sort">筛选条件</param>
        /// <returns></returns>
        [HttpPost]
        [SecurityDefine]
        public PagingList<LoginRecordDetailDto> GetRelatedRecords([ApiSeat(ApiSeats.ActionStart)] int id, [ApiSeat(ApiSeats.ActionStart)] int index, [ApiSeat(ApiSeats.ActionStart)] int limit,
            [FromBody] LoginRecordSort sort = default)
        {
            var query = _appRepository.AsQueryable(false);
            var currentRecord = query.FirstOrDefault(t => t.Id == id);
            if (currentRecord == null)
            {
                throw Oops.Oh("参数错误，请检查后重试");
            }

            // 条件过滤
            query = query.Where(x => x.Account == currentRecord.Account && x.Id != id);

            // 排序之后再进行分页处理
            var pageResult = new PagingList<LoginRecordDetailDto> { Current = index, PageSize = limit, Total = query.Count() };
            query = query.AsSortQuery(sort, o => o.LoginTime)
                .AsPagedQuery(index, limit);

            // join left
            pageResult.List = (from a in query.ProjectToType<LoginRecordDetailDto>()
                               join b in _blacklistRepository.AsQueryable(false) on a.Host equals b.HostAddress into temp
                               from c in temp.DefaultIfEmpty()
                               select a.SetBlacklist(c))
                               .Cast<LoginRecordDetailDto>()
                               .ToList();

            return pageResult;
        }
    }
}
